package com.smarthome.api.mobile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Random;

public class ClientSend {
	// 协议集定义--开始//
	public static final byte PACKAGE_HEND_STX = 0x02;// 开始位 0x02
	public static final byte PACKAGE_HEND_RAND = 0x1F;// 随机数 保留
	public static byte PACKAGE_HEND_COMMAND = 0x00;// 指令 区别不同的指令(---变化值---)
	public static final byte PACKAGE_HEND_ADDRESS = 0x00;// 控制器地址 保留
	public static byte PACKAGE_HEND_DOOR = 0x01;// 门编号号 1-4
	public static byte PACKAGE_HEND_LENGTHL = 0x01;// 数据长度低位,下面数据部分的长度.为0则表示没有数据部分,控制器返回高低位颠倒。(---变化值---)
	public static byte PACKAGE_HEND_LENGTHH = 0x00;// 数据长度高位(---变化值---)
	public static byte[] PACKAGE_BODY_DATA;// 数据,指令包含的数据，有些指令没有该部分(---变化值---)
	public static byte PACKAGE_TAIL_CS = 0x02;// 校验位(---变化值---)
	public static final byte PACKAGE_TAIL_ETX = 0x03;// 结束位0x03

	public static final byte DEVICE_RTNMSG_OK = 0x06;// 执行成功： Data ＝06
	public static final byte DEVICE_RTNMSG_FAIL = 0x15;// 执行不成功： Data ＝15
	// 协议集定义--结束//

	// 指令集定义--开始//
	public static final byte COMMAND_KEEP_CONN = 0x56;// 保持连接
	public static final byte COMMAND_DOOR_OPEN = 0x2C;// 开门
	public static final byte COMMAND_DOOR_CLOSE = 0x2E;// 关门
	public static final byte COMMAND_CARD_RECORD = 0x53;// 关门
	public static Socket socket = null;

	// 指令集定义--结束//

	// socket定义参数--开始//
	public static final String SOCKET_IP_ADDRESS = "171.217.88.46";// 测试板IP
	public static final int SOCKET_IP_PORT = 6000;// 测试板连接端口
	public static int oemcode = 23456;

	public static final byte suc = 0x06;

	public static void sendCommand(byte command) throws Exception {
		if (socket == null || socket.isClosed()) {
			socket = new Socket(SOCKET_IP_ADDRESS, SOCKET_IP_PORT);
		}
		socket.setKeepAlive(true);
		socket.setSoTimeout(0);
		socket.sendUrgentData(0xff);

		byte[] headbytes = getHead(command);
		byte[] tailbytes = getTail(headbytes);
		OutputStream outputStream = socket.getOutputStream();
		InputStream is = socket.getInputStream();
		try {
			byte[] byes = new byte[100];
			is.read(byes);
			System.out.println("收到的命令：" + Integer.toHexString(byes[2]));
			if (byes[2] == COMMAND_KEEP_CONN) {
				System.out.println("<-----------心跳连接------------>");
				outputStream.write(headbytes);
				if (PACKAGE_BODY_DATA != null) {
					outputStream.write(PACKAGE_BODY_DATA);
				}
				// 高低位
				byte[] mid = new byte[2];
				mid[0] = (byte) (oemcode >> 8);
				mid[1] = (byte) (oemcode & 0xff);
				outputStream.write(mid);
				outputStream.write(tailbytes);
				outputStream.flush();
			} else if (byes[2] == COMMAND_CARD_RECORD) {
				System.out.println("<-----------刷卡记录------------>");
				outputStream.write(headbytes);
				if (PACKAGE_BODY_DATA != null) {
					outputStream.write(PACKAGE_BODY_DATA);
				}
				// 高低位
				byte[] mid = new byte[1];
				mid[0] = byes[20];

				outputStream.write(mid);
				outputStream.write(tailbytes);
				outputStream.flush();
			}
			is.close();
			// outputStream.close();
		} catch (Exception e) {
			System.out.println("心跳异常!,具体信息为[" + e + "]");
		}
	}

	public static void doCommand(byte command) throws Exception {
		System.out.println("开门：" + socket);
		System.out.println("<-----------开始发送命令------------>");
//		System.out.println("socket关闭状态：" + socket.isClosed());
		if (socket == null || socket.isClosed()) {
			socket = new Socket(SOCKET_IP_ADDRESS, SOCKET_IP_PORT);
		}
		socket.setKeepAlive(true);
		socket.setSoTimeout(0);
		//socket.sendUrgentData(0xff);
		byte[] headbytes = getHead(command);
		byte[] tailbytes = getTail(headbytes);

		OutputStream outputStream = socket.getOutputStream();
		InputStream is = socket.getInputStream();
		try {
			byte[] ddd = new byte[headbytes.length+tailbytes.length];
			for(int i = 0;i<headbytes.length;i++){
				ddd[i]=headbytes[i];
			}
			for(int i=headbytes.length,j = 0;j<tailbytes.length;i++,j++){
				ddd[i]=tailbytes[j];
			}
			printHexString(ddd);
			outputStream.write(ddd);
			outputStream.flush();
			byte[] byes = new byte[8];
			is.read(byes);
			System.out.println("接收到的返回命令：");
			printHexString(byes);
			if (!Integer.toHexString(byes[7]).equals("6")) {
				socket.close();
				doCommand(ClientSend.COMMAND_DOOR_OPEN);
			}
			System.out.println("发送命令：["+byte2hex(headbytes) + byte2hex(tailbytes)+"]");
			System.out.println("命令状态：" + Integer.toHexString(byes[7]));
			is.close();
		} catch (Exception e) {
			System.out.println("开门异常!,具体信息为[" + e + "],重新执行一次命令。");
			socket.close();
			doCommand(ClientSend.COMMAND_DOOR_OPEN);
		}

	}

	private static byte[] getHead(byte command) {
		// 1.组装协议指令
		byte[] headbytes = new byte[8];
		headbytes[0] = PACKAGE_HEND_STX;

		byte[] rand = new byte[1];
		new Random().nextBytes(rand);
		headbytes[1] = rand[0];
		headbytes[2] = command;
		headbytes[3] = PACKAGE_HEND_ADDRESS;
		headbytes[4] = PACKAGE_HEND_DOOR;
		headbytes[5] = PACKAGE_HEND_LENGTHL;
		headbytes[6] = PACKAGE_HEND_LENGTHH;
		headbytes[7] = 0x01;
		return headbytes;
	}

	private static byte[] getTail(byte[] headbytes) {
		PACKAGE_TAIL_CS = headbytes[0];
		for (int i = 1; i < headbytes.length; i++) {
			PACKAGE_TAIL_CS = (byte) (PACKAGE_TAIL_CS ^ headbytes[i]);
		}

		byte[] tailbytes = new byte[2];
		tailbytes[0] = PACKAGE_TAIL_CS;
		tailbytes[1] = PACKAGE_TAIL_ETX;
		return tailbytes;
	}

	public static byte[] toByteArray(InputStream input) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int n = 0;
		while (-1 != (n = input.read(buffer))) {
			output.write(buffer, 0, n);
		}
		return output.toByteArray();
	}

	public static byte[] hex2byte(String hex) {
		String digital = "0123456789ABCDEF";
		char[] hex2char = hex.toCharArray();
		byte[] bytes = new byte[hex.length() / 2];
		int temp;
		for (int i = 0; i < bytes.length; i++) {
			temp = digital.indexOf(hex2char[2 * i]) * 16;
			temp += digital.indexOf(hex2char[2 * i + 1]);
			if (i == 0)
				bytes[i] = (byte) (temp >> 8);
			bytes[i] = (byte) (temp & 0xff);
		}
		return bytes;
	}
	private static String byte2hex(byte[] buffer) {
		String h = "";

		for (int i = 0; i < buffer.length; i++) {
			String temp = Integer.toHexString(buffer[i] & 0xFF);
			if (temp.length() == 1) {
				temp = "0" + temp;
			}
			h = h + " " + temp;
		}
		return h.toUpperCase();
	}
	 /**
     * 将指定byte数组以16进制的形式打印到控制台
     * 
     * @param hint
     *            String
     * @param b
     *            byte[]
     * @return void
     */
    public static void printHexString(byte[] b)
    {
        for (int i = 0; i < b.length; i++)
        {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1)
            {
                hex = '0' + hex;
            }
            System.out.print(hex.toUpperCase() + " ");
        }
        System.out.println("");
    }
}